<!DOCTYPE >
<html>
  <head>
    <title>Transform Fonts</title>
    <style type="text/css">
      body {
        padding: 20px;
        background: white;
        font-family: Helvetica Neue, Arial, sans-serif;
        font-size: 18px;
        color: green;
        margin: auto;
        height: 80%;
        text-align: center;
      }

      a {
        color: #green;
        text-decoration: none;
        border-bottom: dotted 2px;
      }

      a.button {
        color: #green;
        background: #bfb;
        text-decoration: none;
        padding: 5px;
        margin: 2px;
        border: 5px solid #aea;
      }

      div#error {
        width: 60%;
        padding: 10px;
        color: red;
        background: #faa;
        border: 15px solid #d99;
      }
    </style>
  </head>
  <body>
    <h1>Glyphs</h1>
    <p>
      <em>Cross indicates render coordinates.</em>
    </p>
    <canvas id="glyphs"></canvas>
    <p></p>
    <h3>Glyph Code</h3>
    <a href="#" id="download" download="VexFlowFont.js">Download</a>
    <p></p>
    <textarea id="source" style="width: 800; height: 200"></textarea>
    <p>For more information visit <a href="http://0xfe.blogspot.com">0xfe.blogspot.com</a>.</p>
    <script src="../../../build/cjs/vexflow-debug.js"></script>
    <script src="gonville_all.ts"></script>
    <script src="microtonal.ts"></script>
    <script>
      function combineFonts({ fontFamily, fonts, validCodes }) {
        // Merge glyphs from each font together
        const glyphCodeToData = fonts.reduce(
          (glyphCodeToData, font) => Object.assign(glyphCodeToData, font.glyphs),
          {}
        );

        /*
        // Omit unused glyph codes. Uncomment this section to show only glyphs that are used.
        for (const glyphCode of Object.keys(glyphCodeToData)) {
          if (!validCodes.includes(glyphCode)) {
            delete glyphCodeToData[glyphCode];
          }
        }
        */

        // Return a new font with combined glyph set and new fontFamily name.
        var newFont = Object.assign({}, GonvilleAll, { glyphs: glyphCodeToData, fontFamily });
        delete newFont.original_font_information;
        return newFont;
      }

      function drawGlyphs(font) {
        const canvas = document.getElementById('glyphs');
        const glyphs = font.getGlyphs();

        const canvasHeight = ((Object.keys(glyphs).length + 1) / (800 / (60 * 2))) * 60;

        // Retina display trick
        canvas.height = canvasHeight * 2;
        canvas.width = 1600;
        canvas.style.height = canvasHeight + 'px';
        canvas.style.width = 800 + 'px';
        var ctx = canvas.getContext('2d');
        ctx.scale(2, 2);

        ctx.font = '16px Arial';

        let x = 0;
        let y = 40;

        Object.keys(glyphs).forEach((glyphCode) => {
          if (!glyphs[glyphCode].o) {
            console.log(glyphCode + ' has no outline');
            return;
          }

          ctx.fillStyle = '#666';
          ctx.fillText(glyphCode, x, y);
          x += 60;

          ctx.strokeStyle = '#888';
          ctx.beginPath();
          ctx.moveTo(x - 5, y);
          ctx.lineTo(x + 5, y);
          ctx.stroke();

          ctx.beginPath();
          ctx.moveTo(x, y - 5);
          ctx.lineTo(x, y + 5);
          ctx.stroke();

          ctx.fillStyle = 'green';

          try {
            var glyph = new Vex.Flow.Glyph(glyphCode, 40, { cache: false, font });
            glyph.render(ctx, x, y);
          } catch (e) {
            console.error(e);
          }

          x += 60;

          if (x >= 800) {
            x = 0;
            y += 60;
          }
        });
      }

      function generateFontString(font) {
        return `export const VexFlowFont = ${JSON.stringify(font)};`
          .replace(/\},/g, '},\n')
          .replace(/"glyphs":\{/g, '\n"glyphs":{\n')
          .replace(/\}\}/g, '}\n}')
          .replace(/\};/, '\n};');
      }

      function populateTextArea(string) {
        document.getElementById('source').value = string;
        document.getElementById('download').href = 'data:text/plain,' + string;
      }

      // List of glyphs that we want.
      const validGlyphCodes = [
        'v0',
        'v1',
        'v2',
        'v3',
        'v4',
        'v5',
        'v6',
        'v7',
        'v8',
        'v9',
        'va',
        'vb',
        'vf',
        'vc',
        'v10',
        'v11',
        'v18',
        'v1b',
        'v1d',
        'v1e',
        'v1f',
        'v22',
        'v23',
        'v25',
        'v26',
        'v27',
        'v28',
        'v2a',
        'v2d',
        'v2f',
        'v30',
        'v33',
        'v38',
        'v3b',
        'v3c',
        'v3e',
        'v3f',
        'v40',
        'v41',
        'v42',
        'v43',
        'v44',
        'v45',
        'v46',
        'v47',
        'v49',
        'v4a',
        'v4d',
        'v4e',
        'v52',
        'v54',
        'v55',
        'v58',
        'v59',
        'v5b',
        'v5c',
        'v62',
        'v70',
        'v72',
        'v74',
        'v75',
        'v79',
        'v7c',
        'v7d',
        'v7f',
        'v80',
        'v81',
        'v83',
        'v84',
        'v8b',
        'v8c',
        'v8f',
        'v92',
        'v93',
        'v94',
        'v95',
        'v97',
        'v9a',
        'v9b',
        'v9c',
        'vaa',
        'va3',
        'va5',
        'va9',
        'vad',
        'vb6',
        'vb3',
        'vb9',
        'vba',
        'vbf',
        'vc3',

        // Microtonal
        // db
        'v9e',
        // d
        'vab',
        // bb/
        'v90',
        // ++
        'v51',
        // +
        'v78',
        'v7a',
        'v8d',
        'vb7',
        'v39',

        // Pedal Open
        'v36',
        // Pedal close
        'v5d',
        // Caesura straight
        'v34',
        // Caesura curved
        'v4b',
        // Breath
        'v6c',
        // Tick
        'v6f',
        // Marcato
        'v5a',
        // Marcato Inverted
        'v8a',
        // Turn
        'v72',
        // Turn inverted
        'v33',
        // Mordent inverted
        'v45',
        // upprall
        'v60',
        // downprall
        'vb4',
        // prallup
        'v6d',
        // pralldown
        'v2c',
        // upmordent
        'v29',
        // downmordent
        'v68',
        // lineprall
        'v20',
        // prall
        'v1e',
        // prallprall
        'v86',
        // breve
        'v53',
        // breve rest
        'v31',
        // dynamics letter r
        'vb1',
        // sori (microtonal accidental)
        'vd0',
        // koron (microtonal accidental)
        'vd1',
      ];

      const combinedFont = combineFonts({
        fontFamily: 'VexFlowFont',
        fonts: [GonvilleAll, Microtonal],
        validCodes: validGlyphCodes,
      });

      // Version 4.0.0
      const font = Vex.Flow.Font.load('VexFlowFont', combinedFont);
      Vex.Flow.setMusicFont('VexFlowFont');

      // Version 3.0.9
      // const font = new Vex.Flow.Font('VexFlowFont', {} /* metrics */, combinedFont /* fontData */);
      // Vex.Flow.DEFAULT_FONT_STACK = [font];

      drawGlyphs(font);
      populateTextArea(generateFontString(combinedFont));
    </script>
  </body>
</html>
